package com.xxx.system.service.impl;


import com.github.pagehelper.PageHelper;
import com.xxx.system.domain.Menu;
import com.xxx.system.mapper.MenuMapper;
import com.xxx.system.query.MenuQuery;
import com.xxx.system.service.IMenuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
// 查询事务控制方式：设置只读 支持当前事务，如果没有当前事务，就以非事务方法执行。
@Transactional(readOnly = true, propagation = Propagation.SUPPORTS)
public class MenuServiceImpl implements IMenuService {
    @Autowired
    private MenuMapper menuMapper;

    @Override
    @Transactional
    public void addMenu(Menu Menu) {
        menuMapper.addMenu(Menu);
    }

    @Override
    @Transactional
    public void updateMenu(Menu Menu) {
        menuMapper.updateMenu(Menu);
    }

    @Override
    @Transactional
    public void deteleById(Long id) {
        menuMapper.deteleById(id);
    }

    @Override
    public Menu findOne(Long id) {
        return menuMapper.findOne(id);
    }

    @Override
    public List<Menu> findAll() {
        List<Menu> list = menuMapper.findAll();//从数据库中查询部门树
        return list;
    }

    @Override
    public List<Menu> queryPage(MenuQuery menuQuery) {
        //开始设置分页信息
        //干了三件事情：
        //1.查询总条数 2.根据驱动名称自动添加分页 3.分页查询返回结果
        PageHelper.startPage(menuQuery.getCurrentPage(), menuQuery.getPageSize());
        //直接高级查询，自动实现分页
        return menuMapper.queryPage(menuQuery);
    }

    @Override
    @Transactional
    public void deleteMenuByIds(Long[] ids) {
        menuMapper.deleteMenuByIds(ids);
    }

    //无限极树
    /*1. 一次性查询出所有数据，放到内存中，可以使用map
    2. 从所有数据中找出第一层级/顶级类型：这就是我们需要返回的数据
    3. 遍历所有类型只要不是第一层级的，找自己的上级，并将自己放入上级的children中*/
    @Override
    public List<Menu> getMenuTree(List<Menu> list, Long id) {
        //1.查询所有类型,redis取值
        //2.把所有list转换为map,id为key,自己为value
        Map<Long, Menu> menuMap =
                list.stream().collect(
                        Collectors.toMap(Menu::getId, (d) -> d)
                );
        //3.定义返回的typeTree集合
        List<Menu> menuTree = new ArrayList<Menu>();
        //4.找到顶层类型，没有上级类型就是顶级类型
        for (Menu menu : list) {
            //equals自己的id直接跳过，Long缓存问题，用equals

            if (menu.getId().equals(id)) continue;

            if (menu.getParentId() == null) {
                menuTree.add(menu);
            } else {//非顶级类型加入到父级类型下
                //找到父类型
                Menu parentMenu = menuMap.get(menu.getParentId());
                //添加自己到父类型的子类型集合中
                parentMenu.getChildren().add(menu);
            }
        }
        return menuTree;
    }
}